import * as THREE from 'three';
import { BaseDemo } from './BaseDemo';
import { Emitter, GravityForceField, ParticleSystem, Tween } from '../index';
import { getSPEMat } from '../util';
import GUI from "three/examples/jsm/libs/lil-gui.module.min.js";

export class FireworksDemo extends BaseDemo {
    private emitter?: Emitter;
    private gravity?: GravityForceField;
    private colorTween?: Tween<THREE.Vector3>;
    private sizeTween?: Tween<number>;

    constructor(scene: THREE.Scene) {
        super('烟花效果', '经典烟花爆炸效果，展示粒子发射、重力、颜色变化', scene);
    }

    init(): void {
        // 创建烟花材质
        const material = getSPEMat({
            color: new THREE.Color(0xffffff),
            size: 5,
            sizeAttenuation: false,
            vertexColors: true,
            depthTest: true,
            depthWrite: false,
            blending: THREE.AdditiveBlending,
            transparent: true,
            opacity: 0.8,
        });

        // 创建发射器 - 球形爆炸
        this.emitter = new Emitter({
            origin: new THREE.Vector3(0, 20, 0),
            rate: 100,
            life: 3,
            emitterLife: 1, // 短暂爆发
            volecity: new THREE.Vector3(0, 0, 0),
            // randomVelocity: {
            //     direction: new THREE.Vector3(0, 1, 0),
            //     coneAngle: Math.PI, // 全方向爆炸
            //     speedMin: 15,
            //     speedMax: 25,
            // },
            normalVelocity:{
                enabled:true,
                speed:5,
                speedRange: [0.1,5]
            },
            angle: 0,
            size: 1,
            shape: 'sphere',
            shapeParams:{
                radius:1
            },
            material: material,
            maxCount: 2000,
        });

        // 重力场
        this.gravity = new GravityForceField(new THREE.Vector3(0, -9.8, 0));

        // 颜色变化：从红色到黄色到透明  bug 现在tween还不能用color对象，
        this.colorTween = new Tween(
            [0, 1, 2, 3],
            [
                new THREE.Vector3(1, 0.2, 0.1), // 红色
                new THREE.Vector3(1, 0.8, 0.2), // 橙色
                new THREE.Vector3(1, 1, 0.5),   // 黄色
                new THREE.Vector3(0.5, 0.5, 0.5) // 灰色
            ],
            'color'
        );

//   this.colorTween.lerp = function (t = 0) {
//     let i = 0;
//     let n = this.times.length;
//     while (i < n && t > this.times[i]) i++;
//     if (i === 0) return this.values[0];
//     if (i === n) return this.values[n - 1];
//     let p = (t - this.times[i - 1]) / (this.times[i] - this.times[i - 1]);
//     const tv = this.values[i - 1].clone().lerp(this.values[i], p);


//     color1.setHSL(tv.r, tv.g, tv.b);

//     return new THREE.Vector3(color1.r, color1.g, color1.b);

//   }

        // 尺寸变化：从小到大再到小
        this.sizeTween = new Tween(
            [0, 0.5, 3],
            [0.5, 2, 0.1],
            'size'
        );

        // 创建粒子系统
        this.particleSystem = new ParticleSystem(
            [this.emitter],
            [this.gravity],
            [ this.colorTween,this.sizeTween],
            []
        );
    }

    protected createControls(folder: GUI): void {
        if (!this.emitter || !this.gravity) return;

        const controls = {
            explode: () => {
                if (this.emitter) {
                    this.emitter.reLive(1);
                }
            },
            height: 30,
            power: 20,
            gravity: -9.8,
            particleLife: 3,
            explosionRate: 100,
        };

        folder.add(controls, 'explode').name('引爆烟花');
        
        folder.add(controls, 'height', 10, 50)
            .name('爆炸高度')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.origin.y = value;
                }
            });

        folder.add(controls, 'power', 5, 50)
            .name('爆炸威力')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.randomVelocity.speedMax = value;
                    this.emitter.randomVelocity.speedMin = value * 0.6;
                }
            });

        folder.add(controls, 'gravity', -20, 0)
            .name('重力强度')
            .onChange((value: number) => {
                if (this.gravity) {
                    this.gravity.gravity.y = value;
                }
            });

        folder.add(controls, 'particleLife', 1, 10)
            .name('粒子生命')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.life = value;
                }
            });

        folder.add(controls, 'explosionRate', 500, 5000)
            .name('爆炸粒子数')
            .onChange((value: number) => {
                if (this.emitter) {
                    this.emitter.rate = value;
                }
            });

        folder.open();
        this.initMatGUI( this.emitter.material,folder)    
        
    }
}